package com.zenithmind.document.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zenithmind.common.context.UserContext;
import com.zenithmind.common.result.Result;
import com.zenithmind.document.pojo.dto.DocumentAccessLogCreateDTO;
import com.zenithmind.document.pojo.query.DocumentAccessLogQueryDTO;
import com.zenithmind.document.pojo.vo.DocumentAccessLogVO;
import com.zenithmind.document.service.DocumentAccessLogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import java.util.List;

/**
 * 文档访问日志控制器
 * 遵循单一职责原则：专注于访问日志相关的HTTP接口
 * 遵循依赖倒置原则：依赖抽象服务接口
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@RestController
@RequestMapping("/api/document/access-log")
@RequiredArgsConstructor
@Validated
@Tag(name = "文档访问日志管理", description = "文档访问日志相关接口")
public class DocumentAccessLogController {

    private final DocumentAccessLogService documentAccessLogService;

    @PostMapping
    @Operation(summary = "记录访问日志", description = "记录文档访问日志")
    public Result<DocumentAccessLogVO> recordAccess(@Valid @RequestBody DocumentAccessLogCreateDTO createDTO) {
        log.info("记录访问日志请求: documentId={}", createDTO.getDocumentId());
        
        DocumentAccessLogVO result = documentAccessLogService.recordAccess(createDTO);
        
        return Result.success(result);
    }

    @PostMapping("/view/{documentId}")
    @Operation(summary = "记录文档查看", description = "记录文档查看访问")
    public Result<DocumentAccessLogVO> recordView(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId,
            HttpServletRequest request) {
        
        log.info("记录文档查看请求: documentId={}", documentId);
        
        String userId = UserContext.getUserId();
        String userAgent = request.getHeader("User-Agent");
        String ipAddress = getClientIpAddress(request);
        
        DocumentAccessLogVO result = documentAccessLogService.recordView(documentId, userId, userAgent, ipAddress);
        
        return Result.success(result);
    }

    @PostMapping("/download/{documentId}")
    @Operation(summary = "记录文档下载", description = "记录文档下载访问")
    public Result<DocumentAccessLogVO> recordDownload(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId,
            HttpServletRequest request) {
        
        log.info("记录文档下载请求: documentId={}", documentId);
        
        String userId = UserContext.getUserId();
        String userAgent = request.getHeader("User-Agent");
        String ipAddress = getClientIpAddress(request);
        
        DocumentAccessLogVO result = documentAccessLogService.recordDownload(documentId, userId, userAgent, ipAddress);
        
        return Result.success(result);
    }

    @PostMapping("/share/{documentId}")
    @Operation(summary = "记录文档分享", description = "记录文档分享访问")
    public Result<DocumentAccessLogVO> recordShare(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId,
            @Parameter(description = "分享类型", required = true) @RequestParam @NotBlank String shareType,
            HttpServletRequest request) {
        
        log.info("记录文档分享请求: documentId={}, shareType={}", documentId, shareType);
        
        String userId = UserContext.getUserId();
        String userAgent = request.getHeader("User-Agent");
        String ipAddress = getClientIpAddress(request);
        
        DocumentAccessLogVO result = documentAccessLogService.recordShare(documentId, userId, shareType, userAgent, ipAddress);
        
        return Result.success(result);
    }

    @GetMapping("/page")
    @Operation(summary = "分页查询访问日志", description = "分页查询文档访问日志列表")
    public Result<IPage<DocumentAccessLogVO>> getAccessLogPage(@Valid DocumentAccessLogQueryDTO queryDTO) {
        log.info("分页查询访问日志请求");
        
        IPage<DocumentAccessLogVO> result = documentAccessLogService.getAccessLogPage(queryDTO);
        
        return Result.success(result);
    }

    @GetMapping("/document/{documentId}")
    @Operation(summary = "获取文档访问日志", description = "获取指定文档的访问日志")
    public Result<List<DocumentAccessLogVO>> getDocumentAccessLogs(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId,
            @Parameter(description = "限制数量") @RequestParam(required = false, defaultValue = "20") Integer limit) {
        
        log.info("获取文档访问日志请求: documentId={}", documentId);
        
        List<DocumentAccessLogVO> result = documentAccessLogService.getDocumentAccessLogs(documentId, limit);
        
        return Result.success(result);
    }

    @GetMapping("/user")
    @Operation(summary = "获取用户访问日志", description = "获取当前用户的访问日志")
    public Result<List<DocumentAccessLogVO>> getUserAccessLogs(
            @Parameter(description = "限制数量") @RequestParam(required = false, defaultValue = "20") Integer limit) {
        
        log.info("获取用户访问日志请求");
        
        String userId = UserContext.getUserId();
        List<DocumentAccessLogVO> result = documentAccessLogService.getUserAccessLogs(userId, limit);
        
        return Result.success(result);
    }

    @GetMapping("/user/{userId}")
    @Operation(summary = "获取指定用户访问日志", description = "获取指定用户的访问日志")
    public Result<List<DocumentAccessLogVO>> getUserAccessLogs(
            @Parameter(description = "用户ID", required = true) @PathVariable @NotBlank String userId,
            @Parameter(description = "限制数量") @RequestParam(required = false, defaultValue = "20") Integer limit) {
        
        log.info("获取指定用户访问日志请求: userId={}", userId);
        
        List<DocumentAccessLogVO> result = documentAccessLogService.getUserAccessLogs(userId, limit);
        
        return Result.success(result);
    }

    @GetMapping("/statistics/{documentId}")
    @Operation(summary = "获取访问统计", description = "获取文档访问统计信息")
    public Result<Object> getAccessStatistics(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId,
            @Parameter(description = "统计天数") @RequestParam(required = false, defaultValue = "7") Integer days) {
        
        log.info("获取访问统计请求: documentId={}, days={}", documentId, days);
        
        Object result = documentAccessLogService.getAccessStatistics(documentId, days);
        
        return Result.success(result);
    }

    @GetMapping("/hot")
    @Operation(summary = "获取热门访问文档", description = "获取热门访问文档列表")
    public Result<List<Object>> getHotAccessDocuments(
            @Parameter(description = "统计天数") @RequestParam(required = false, defaultValue = "7") Integer days,
            @Parameter(description = "限制数量") @RequestParam(required = false, defaultValue = "10") Integer limit) {
        
        log.info("获取热门访问文档请求: days={}, limit={}", days, limit);
        
        List<Object> result = documentAccessLogService.getHotAccessDocuments(days, limit);
        
        return Result.success(result);
    }

    @GetMapping("/trend/{documentId}")
    @Operation(summary = "获取访问趋势", description = "获取文档访问趋势数据")
    public Result<List<Object>> getAccessTrend(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId,
            @Parameter(description = "统计天数") @RequestParam(required = false, defaultValue = "30") Integer days) {
        
        log.info("获取访问趋势请求: documentId={}, days={}", documentId, days);
        
        List<Object> result = documentAccessLogService.getAccessTrend(documentId, days);
        
        return Result.success(result);
    }

    @GetMapping("/behavior")
    @Operation(summary = "获取用户访问行为", description = "获取当前用户访问行为分析")
    public Result<Object> getUserAccessBehavior(
            @Parameter(description = "统计天数") @RequestParam(required = false, defaultValue = "30") Integer days) {
        
        log.info("获取用户访问行为请求: days={}", days);
        
        String userId = UserContext.getUserId();
        Object result = documentAccessLogService.getUserAccessBehavior(userId, days);
        
        return Result.success(result);
    }

    @GetMapping("/ip-statistics")
    @Operation(summary = "获取IP访问统计", description = "获取IP访问统计信息")
    public Result<List<Object>> getIpAccessStatistics(
            @Parameter(description = "统计天数") @RequestParam(required = false, defaultValue = "7") Integer days,
            @Parameter(description = "限制数量") @RequestParam(required = false, defaultValue = "20") Integer limit) {
        
        log.info("获取IP访问统计请求: days={}, limit={}", days, limit);
        
        List<Object> result = documentAccessLogService.getIpAccessStatistics(days, limit);
        
        return Result.success(result);
    }

    @GetMapping("/device-statistics")
    @Operation(summary = "获取设备访问统计", description = "获取设备访问统计信息")
    public Result<List<Object>> getDeviceAccessStatistics(
            @Parameter(description = "统计天数") @RequestParam(required = false, defaultValue = "7") Integer days) {
        
        log.info("获取设备访问统计请求: days={}", days);
        
        List<Object> result = documentAccessLogService.getDeviceAccessStatistics(days);
        
        return Result.success(result);
    }

    @GetMapping("/browser-statistics")
    @Operation(summary = "获取浏览器访问统计", description = "获取浏览器访问统计信息")
    public Result<List<Object>> getBrowserAccessStatistics(
            @Parameter(description = "统计天数") @RequestParam(required = false, defaultValue = "7") Integer days) {
        
        log.info("获取浏览器访问统计请求: days={}", days);
        
        List<Object> result = documentAccessLogService.getBrowserAccessStatistics(days);
        
        return Result.success(result);
    }

    @GetMapping("/time-distribution")
    @Operation(summary = "获取访问时间分布", description = "获取访问时间分布统计")
    public Result<List<Object>> getAccessTimeDistribution(
            @Parameter(description = "统计天数") @RequestParam(required = false, defaultValue = "7") Integer days) {
        
        log.info("获取访问时间分布请求: days={}", days);
        
        List<Object> result = documentAccessLogService.getAccessTimeDistribution(days);
        
        return Result.success(result);
    }

    @PostMapping("/detect-abnormal")
    @Operation(summary = "检测异常访问", description = "检测异常访问行为")
    public Result<Boolean> detectAbnormalAccess(
            @Parameter(description = "文档ID", required = true) @RequestParam @NotBlank String documentId,
            HttpServletRequest request) {
        
        log.info("检测异常访问请求: documentId={}", documentId);
        
        String userId = UserContext.getUserId();
        String ipAddress = getClientIpAddress(request);
        
        Boolean result = documentAccessLogService.detectAbnormalAccess(documentId, userId, ipAddress);
        
        return Result.success(result);
    }

    @PostMapping("/cleanup")
    @Operation(summary = "清理过期日志", description = "清理过期的访问日志")
    public Result<Integer> cleanupExpiredLogs(
            @Parameter(description = "保留天数") @RequestParam(required = false, defaultValue = "90") Integer retentionDays) {
        
        log.info("清理过期日志请求: retentionDays={}", retentionDays);
        
        Integer result = documentAccessLogService.cleanupExpiredLogs(retentionDays);
        
        return Result.success(result);
    }

    @GetMapping("/export")
    @Operation(summary = "导出访问日志", description = "导出访问日志数据")
    public Result<Object> exportAccessLogs(@Valid DocumentAccessLogQueryDTO queryDTO) {
        log.info("导出访问日志请求");
        
        Object result = documentAccessLogService.exportAccessLogs(queryDTO);
        
        return Result.success(result);
    }

    @GetMapping("/real-time")
    @Operation(summary = "获取实时访问统计", description = "获取实时访问统计数据")
    public Result<Object> getRealTimeAccessStatistics() {
        log.info("获取实时访问统计请求");
        
        Object result = documentAccessLogService.getRealTimeAccessStatistics();
        
        return Result.success(result);
    }

    @PostMapping("/batch")
    @Operation(summary = "批量记录访问", description = "批量记录访问日志")
    public Result<Integer> batchRecordAccess(@RequestBody @NotEmpty List<DocumentAccessLogCreateDTO> accessLogs) {
        log.info("批量记录访问请求: size={}", accessLogs.size());
        
        Integer result = documentAccessLogService.batchRecordAccess(accessLogs);
        
        return Result.success(result);
    }

    @PostMapping("/sync")
    @Operation(summary = "同步访问统计", description = "同步访问统计数据")
    public Result<Boolean> syncAccessStatistics() {
        log.info("同步访问统计请求");
        
        Boolean result = documentAccessLogService.syncAccessStatistics();
        
        return Result.success(result);
    }

    /**
     * 获取客户端IP地址
     */
    private String getClientIpAddress(HttpServletRequest request) {
        String xForwardedFor = request.getHeader("X-Forwarded-For");
        if (xForwardedFor != null && !xForwardedFor.isEmpty() && !"unknown".equalsIgnoreCase(xForwardedFor)) {
            return xForwardedFor.split(",")[0];
        }
        
        String xRealIp = request.getHeader("X-Real-IP");
        if (xRealIp != null && !xRealIp.isEmpty() && !"unknown".equalsIgnoreCase(xRealIp)) {
            return xRealIp;
        }
        
        return request.getRemoteAddr();
    }
}
